using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.Build;
using UnityEngine;
using LitJson;
using NUnit.Framework.Constraints;

public class BundlePackage
{
    static string streamingAssetsPath = Application.dataPath + "/StreamingAssets/";

    static List<string> gameNames = new List<string>()
    {
        // "game145",
        // "game147",
        // "game148",
        // "game149",
        // "game150",
        // "game151",
        // "game245",
        // "game246",
        // "game250",
        // "game533",
        // "game534",
        // "game535",
        // "game536",
        // "game537",
    };

    [MenuItem("Tools/PlayerPrefsDeleteAll")]
    static void PlayerPrefsDeleteAll()
    {
        PlayerPrefs.DeleteAll();
    }

    [MenuItem("Build/BuildAssetbundle")]
    static void BuildABs()
    {
        BuildABs(EditorUserBuildSettings.activeBuildTarget);
    }

    public static void BuildABs(BuildTarget target)
    {
        RefreshAssetBundleNames();

        //打包后的资源存放路径，这个路径根据项目情况不定
        string outputPath = Application.streamingAssetsPath;

        //if (Directory.Exists(outputPath))
        //{
        //    Directory.Delete(outputPath, true);
        //}
        //Directory.CreateDirectory(outputPath);

        if (!Directory.Exists(outputPath))
        {
            Directory.CreateDirectory(outputPath);
        }
        AssetDatabase.Refresh();

        //BuildAssetBundle函数后的三个参数分别为：存储路径；压缩方式；资源目标平台

        var a = BuildPipeline.BuildAssetBundles(outputPath, BuildAssetBundleOptions.ChunkBasedCompression, target);


        AssetDatabase.Refresh();
        BuildFileIndex();
        BuildVersion();
        Debug.LogError("build finsh-" + DateTime.Now);
    }


    //[MenuItem("Build/BuildVersionAndFiles")]
    //static void BuildVersionAndFiles()
    //{
    //    BuildFileIndex();
    //    BuildVersion();
    //}

    /// <summary>
    /// 清除之前设置过的AssetBundleName，避免产生不必要的资源也打包
    /// 工程中只要设置了AssetBundleName的，都会进行打包
    /// </summary>
    [MenuItem("Build/ClearAssetBundleNames")]
    static void ClearAssetBundlesName()
    {
        int length = AssetDatabase.GetAllAssetBundleNames().Length;
        string[] oldAssetBundleNames = new string[length];
        for (int i = 0; i < length; i++)
        {
            oldAssetBundleNames[i] = AssetDatabase.GetAllAssetBundleNames()[i];
        }

        for (int j = 0; j < oldAssetBundleNames.Length; j++)
        {
            AssetDatabase.RemoveAssetBundleName(oldAssetBundleNames[j], true);
        }
    }



    static void RefreshAssetBundleNames()
    {
        string rootPath = Application.dataPath + "/";
        string baseDir = "Assets/";
        DirectoryInfo direction = new DirectoryInfo(baseDir + GameConfig.ResourceDir);
        FileInfo[] files = direction.GetFiles("*", SearchOption.AllDirectories);

        for (int i = 0; i < files.Length; i++)
        {
            if (files[i].Name.EndsWith(".meta"))
            {
                continue;
            }
            if (files[i].FullName.Contains(".idea"))
            {
                continue;
            }
            string relative = files[i].FullName.Remove(0, rootPath.Length);
            int index = relative.IndexOf(".");
            //string bundleName = relative.Remove(index, relative.Length-index);
            string bundleName = files[i].DirectoryName.Remove(0, rootPath.Length) + ".unity3d";

            AssetImporter ai = AssetImporter.GetAtPath(baseDir + relative);
            ai.SetAssetBundleNameAndVariant(bundleName, null);

            if (relative.EndsWith(".prefab"))
            {
                string relative1 = relative.Replace('\\', '/');
                string[] dependencies = AssetDatabase.GetDependencies(baseDir + relative1);
                for (int j = 0; j < dependencies.Length; j++)
                {
                    string dependencyPath = dependencies[j];

                    if (dependencyPath.EndsWith(".bytes") || dependencyPath.EndsWith("_Data.asset"))
                    {
                        AssetImporter dependencyAi = AssetImporter.GetAtPath(dependencyPath);
                        dependencyAi.SetAssetBundleNameAndVariant(bundleName, null);
                    }
                }
            }
        }

        AssetDatabase.Refresh();

    }
    static List<string> paths = new List<string>();
    static List<string> files = new List<string>();

    static void BuildFileIndex()
    {
        string resPath = Application.dataPath + "/StreamingAssets/";
        ///----------------------创建文件列表-----------------------
        string newFilePath = resPath + "/files.txt";
        if (File.Exists(newFilePath)) File.Delete(newFilePath);

        for (int i = 0; i < gameNames.Count; i++)
        {
            newFilePath = resPath + $"/{gameNames[i]}.txt";
            if (File.Exists(newFilePath)) File.Delete(newFilePath);
        }

        paths.Clear(); files.Clear();
        Recursive(resPath);


        Dictionary<string,List<string>> gamefileDic = new Dictionary<string, List<string>>();
        for (int i = 0; i < gameNames.Count; i++)
        {
            gamefileDic[gameNames[i]] = new List<string>();
        }
        for (int i = files.Count-1; i >=0 ; i--)
        {
            string file = files[i];
      
            if (file.EndsWith(".meta") || file.Contains(".DS_Store") || file.EndsWith(".manifest") || file.Contains("build_info") || file.Contains("version.txt")) continue;
            for (int j = 0; j < gameNames.Count; j++)
            {
                string gameName = gameNames[j];
                if (file.Contains(gameName))
                {
                    gamefileDic[gameName].Add(file);
                    files.RemoveAt(i);
                    break;
                }
            }
        }
        foreach (var item in gamefileDic)
        {
            WriteFiles(resPath + $"/{item.Key}.txt", resPath, item.Value);
        }
        WriteFiles(resPath + $"/files.txt", resPath, files);
        AssetDatabase.Refresh();
    }

    public static void WriteFiles(string newFilePath,string resPath, List<string> files)
    {
        FileStream fs = new FileStream(newFilePath, FileMode.CreateNew);
        StreamWriter sw = new StreamWriter(fs);
        for (int i = 0; i < files.Count; i++)
        {
            string file = files[i];
            string ext = Path.GetExtension(file);
            if (file.EndsWith(".meta") || file.Contains(".DS_Store") || file.EndsWith(".manifest") || file.Contains("build_info") || file.Contains("version.txt")) continue;
            long size = new FileInfo(file).Length;
            string md5 = Utils.md5file(file);
            string value = file.Replace(resPath, string.Empty);
            sw.WriteLine(value + "|" + md5 + "|" + size);
        }
        sw.Close(); fs.Close();
    }

    

    /// <summary>
    /// 遍历目录及其子目录
    /// </summary>
    static void Recursive(string path)
    {
        string[] names = Directory.GetFiles(path);
        string[] dirs = Directory.GetDirectories(path);
        foreach (string filename in names)
        {
            string ext = Path.GetExtension(filename);
            if (ext.Equals(".meta")) continue;
            files.Add(filename.Replace('\\', '/'));
        }
        foreach (string dir in dirs)
        {
            paths.Add(dir.Replace('\\', '/'));
            Recursive(dir);
        }
    }

    static void BuildVersion()
    {
        string fileName = "version.txt";

        string devVersionPath = Path.Combine(Application.dataPath, fileName);
        Version version = new Version();
        if (File.Exists(devVersionPath))
        {
            string text = File.ReadAllText(devVersionPath);
            version = JsonMapper.ToObject<Version>(text);
        }
        version.moudleList = new List<MoudleVersion>();
        for (int i = 0; i < gameNames.Count; i++)
        {
            version.moudleList.Add(new MoudleVersion()
            {
                gameName = gameNames[i],
            });
        }
        version.smallVersion++;
        File.WriteAllText(devVersionPath, JsonUtility.ToJson(version));
        File.WriteAllText(Path.Combine(streamingAssetsPath, fileName), JsonMapper.ToJson(version));
        AssetDatabase.Refresh();
    }
}
